#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include "hosts.h"
#include "fileutil.h"
#include "exitcode.h"

static int dbd_client_port=3567;

static char dbd_config_path[] = "/home/gesuper/.distbuild";
static char dbd_config_hosts[] = "hosts";
static char dbd_config_state[] = "state";


struct dbd_hostdef* dbd_init_hostdef_by_ip(const char *ip){
	struct dbd_hostdef *p = (struct dbd_hostdef *)malloc( sizeof(struct dbd_hostdef) );
	strcpy(p->ip, ip);
	p->port = dbd_client_port;
	p->task = 0;
}

int dbd_parse_hosts(const char *source, struct dbd_hostdef **hosts, int *count){
	char delime[] = " ";
	char *ip =NULL;
	struct dbd_hostdef *curr, *prev;
	ip = strtok( source, delime );
	curr = dbd_init_hostdef_by_ip(ip);
	*hosts = curr;
	prev = curr;
	(*count) = 1;
	while( (ip = strtok(NULL, delime)) != NULL ) {
		curr = dbd_init_hostdef_by_ip(ip);
		prev->next = curr;
		prev = curr;
		(*count) += 1;
	}   
	return 0;
}

int dbd_parse_state(const char *source, struct dbd_hostdef *hosts){
	char delime[] = " ";
	struct dbd_hostdef *p;
	char *task = NULL;
	
	if(strlen(source) == 0){
		return 0;
	}
	
	task = strtok(source, delime);
	p = hosts;
	while(task != NULL){
		p->task = atoi(task);
		task = strtok(NULL, delime);
		p = p->next;
	}
	return 0;
}

int dbd_get_hostlist(struct dbd_hostdef **hosts, int *count){
	char host_path[100];
	char state_path[100];
	char *body;

	sprintf(host_path, "%s/%s", dbd_config_path, dbd_config_hosts);
	if(dbd_load_file(host_path, &body) == EXIT_IO_ERROR){
		exit(0);
	}
	
	if(body[strlen(body)-1] == '\n')
		body[strlen(body)-1]=0;
	dbd_parse_hosts(body, hosts, count);
	free(body);
	
	sprintf(state_path, "%s/%s", dbd_config_path, dbd_config_state);
	if(!dbd_load_file(state_path, &body)){
		dbd_parse_state(body, *hosts);
		free(body);
	}
	
	return 0;
}

int dbd_write_state_to_file(struct dbd_hostdef *hosts, int count){
	char state_path[100];
	char * body = (char *)malloc(count * 2 * sizeof(char));
	struct dbd_hostdef *p = hosts;
	int len = 0;
	while(p!=NULL){
		len += sprintf(body + len, "%d ", p->task);
		p = p->next;
	}
	if(len !=0) body[len-1]=0;
	
	sprintf(state_path, "%s/%s", dbd_config_path, dbd_config_state);
	dbd_write_file(state_path, body);
	free(body);
	return 0;
}

int dbd_free_hosts(struct dbd_hostdef *hosts){
	struct dbd_hostdef *curr, *next;
	curr = hosts;
	while(curr != NULL){
		next = curr ->next;
		free(curr);
		curr = next;
	}
	return 0;
}

int dbd_pick_one_host(struct dbd_hostdef **out){
	struct dbd_hostdef *hosts, *tmp, *pick;
	int count;
	
	dbd_get_hostlist(&hosts, &count);
	pick = tmp = hosts;
	while((tmp = tmp ->next)!= NULL){
		if(tmp->task < pick -> task)
			pick=tmp;
		if(pick->task == 0)
			break;
	}
	pick->task += 1;
	dbd_write_state_to_file(hosts, count);
	(*out) = (struct dbd_hostdef *)malloc( sizeof(struct dbd_hostdef) );
	strcpy((*out)->ip, pick->ip);
	(*out)->port = pick->port;
	(*out)->task = pick->task;
	dbd_free_hosts(hosts);
	return 0;
}

int dbd_free_one_host(struct dbd_hostdef *target){
	struct dbd_hostdef *hosts, *pick;
	int count;
	
	dbd_get_hostlist(&hosts, &count);
	pick = hosts;
	while(pick != NULL){
		if(strcmp(pick->ip, target->ip)==0)
			break;
		pick = pick->next;
	}
	pick->task-=1;
	dbd_write_state_to_file(hosts, count);
	return 0;
}

int dbd_empty_state(){
	char state_path[100];
	sprintf(state_path, "%s/%s", dbd_config_path, dbd_config_state);
	dbd_write_file(state_path, "");
	return 0;
}
